package com.xyf.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xyf.sys.config.CustomException;
import com.xyf.sys.domain.*;
import com.xyf.sys.mapper.*;
import com.xyf.sys.service.*;
import com.xyf.sys.util.CommonUtils;
import com.xyf.sys.util.WechatHttpUtil;
import com.xyf.sys.vo.UserRealName;
import com.xyf.sys.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author
 * @Date
 * @Description
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IUserAddressService userAddressService;
    @Autowired
    private UserPrinterMapper userPrinterMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private IUserLogisticService userLogisticService;
    @Autowired
    private IDeliveryService deliveryService;
    @Autowired
    private ISysPriceSchemeService priceSchemeService;
    @Autowired
    private IDictDataService dictDataService;
    @Autowired
    private IDeptService deptService;
    @Autowired
    private UserDeptMapper userDeptMapper;
    @Autowired
    private ChannelConfigMapper channelConfigMapper;
    @Autowired
    private IOrderService orderService;


    @Value("${eid.secretId}")
    private String secretId;

    @Value("${eid.secretKey}")
    private String secretKey;


    @Override
    public User get(String id) {
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public User getShortId(String shortId) {
        return userMapper.selectByShortId(shortId);
    }

    @Override
    public User getByMobile(String mobile) {
        return userMapper.selectByMobile(mobile, null);
    }

    @Override
    public User getByMobile(String phone, String appid) {
        return userMapper.selectByMobile(phone, appid);
    }

    @Override
    public User getUser(String openId) {
        return userMapper.selectByOpenid(openId);
    }

    @Override
    public User getUser(String unionid, String appid) {
        return userMapper.selectByUnionidAndAppid(unionid, appid);
    }

    @Override
    public User create(String openid, String unionid, String appid) {
        User user = new User();
        user.setId(openid);
        user.setOpenid(openid);
        user.setAppid(appid);
        user.setShortId(CommonUtils.convertToFixedLengthHash(openid));
        user.setUnionid(unionid);
        user.setParentIds(JSONObject.toJSONString(Arrays.asList("0", openid)));
        user.setCreateTime(new Date());
        userMapper.insert(user);
        return user;
    }

    @Override
    public int update(User body) {
        User user = this.get(body.getUserId());
        if (body.getDeptId() != null && Validator.isMobile(body.getDeptId().toString())){
            User u = this.getByMobile(body.getDeptId().toString());
            body.setDeptId(u.getDeptId());
        }
        if (body.getDefaultRecManAddressId() != null) {
            userAddressService.setDefault(body.getDefaultRecManAddressId(), 2);
        }
        if (body.getDefaultSendManAddressId() != null) {
            userAddressService.setDefault(body.getDefaultSendManAddressId(), 1);
        }
        UserAddress defaultRecManAddress = body.getDefaultRecManAddress();
        if (defaultRecManAddress != null && StringUtils.isNotBlank(defaultRecManAddress.getAddress())){
            UserAddress defaultAddress = userAddressService.getDefaultAddress(user.getUserId(), 2);
            if (defaultAddress == null){
                defaultRecManAddress.setType(2);
                defaultRecManAddress.setIsDefault(1);
                defaultRecManAddress.setUserId(user.getId());
                defaultRecManAddress.setDeptId(user.getDeptId());
                defaultRecManAddress.setCreateBy(user.getUserId());
                userAddressService.add(defaultRecManAddress);
            } else {
                BeanUtil.copyProperties(defaultRecManAddress, defaultAddress, CopyOptions.create(defaultAddress.getClass(), true));
                defaultAddress.setType(2);
                defaultAddress.setDeptId(user.getDeptId());
                defaultAddress.setIsDefault(1);
                defaultAddress.setUpdateBy(user.getId());
                userAddressService.update(defaultAddress);
            }
        }
        if (StringUtils.isNotBlank(body.getRegimentId())) {
            String regimentId = body.getRegimentId();
            User regiment = this.get(regimentId);
            if (regiment == null) {
                regiment = this.getByMobile(regimentId);
            }
            user.setRegimentId(regiment.getId());
        }
        if (StringUtils.isNotBlank(body.getAvatar())) {
            user.setAvatar(body.getAvatar());
        }
        if (StringUtils.isNotBlank(body.getName())) {
            user.setName(body.getName());
        }
        if (body.getDeptId() != null) {
            user.setDeptId(body.getDeptId());
        }
        if (StringUtils.isNotBlank(body.getMobile())) {
            if (!body.getClient()){
                User sysUser = this.getByMobile(body.getMobile());
                if (sysUser != null && !sysUser.getId().equals(user.getId())){
                    throw new CustomException(body.getMobile() + "号码已存在");
                }
            }
            user.setMobile(body.getMobile());
        }
        if (!CollectionUtils.isEmpty(user.getDeptIds())){
            userDeptMapper.deleteByUserId(user.getId());
            List<UserDept> userDepts = user.getDeptIds().stream().map(deptId -> new UserDept(user.getId(), deptId, null)).collect(Collectors.toList());
            for (UserDept userDept : userDepts) {
                userDeptMapper.insert(userDept);
            }
        }
        user.setUpdateTime(new Date());
        user.setLastUpdateTime(new Date());
        return userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public List<User> findNearbyRegimentList(BigDecimal longitude, BigDecimal latitude) {
        return userMapper.selectNearbyRegimentList(longitude, latitude);
    }

    @Override
    public List<User> findNearbyRegimentList(Long deptId, BigDecimal longitude, BigDecimal latitude) {
        return userMapper.selectByDeptIdNearbyRegimentList(deptId, longitude, latitude);
    }

    @Override
    public List<User> getUserList(String userId, String keyword, boolean appEnv, Long roleId) {
        if (StringUtils.isAllBlank(userId, keyword)) {
            return null;
        }
//        List<User> userList = userMapper.selectUserList(userId, keyword, roleId);
        List<User> userList = userMapper.selectUserList2(keyword, appEnv);
        for (User user : userList) {
            List<UserRole> roleList = userRoleMapper.selectDeptRole(user.getId(), user.getDeptId());
            List<Role> roles = new ArrayList<>();
            if (roleList != null) {
                for (UserRole userRole : roleList) {
                    Role role = roleMapper.selectByPrimaryKey(userRole.getRoleId());
                    if ("USER".equals(role.getRoleKey()) && !appEnv) {
                        continue;
                    }
                    roles.add(role);
                }
            }
            user.setRoles(roles);
        }
        return userList;
    }

    @Override
    public UserVo getInfo(String userId) {
        return getInfo(userId, false);
    }

    @Override
    public UserVo getInfo(String userId, boolean appEnv) {
        return getInfo(userId, false, false);
    }

    @Override
    public UserVo getInfo(String userId, boolean appEnv, boolean client) {
        User user = this.get(userId);
        if (user == null) {
            user = getByMobile(userId);
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        List<UserRole> roleList = new ArrayList<>();
        if (appEnv){
            roleList = userRoleMapper.selectUserDefaultRole(user.getId(), user.getDeptId());
        }
        List<UserDept> userDepts = userDeptMapper.selectByUserId(userId);
        userDepts.stream().forEach(userDept -> userDept.setDeptName(deptService.get(userDept.getDeptId()).getDeptName()));
        userVo.setDepts(userDepts);
        if (client){
            Optional<UserDept> optional = userDepts.stream().filter(r -> deptService.get(r.getDeptId()).getMainDept() != null && deptService.get(r.getDeptId()).getMainDept() == 1).findFirst();
            if (optional.isPresent()){
                UserDept dept = optional.get();
                userVo.setDeptId(dept.getDeptId());
                user.setDeptId(dept.getDeptId());
            }
        }
        if (user.getDeptId() != null){
            List<UserPrinter> printers = userPrinterMapper.selectDeptPrinterList(user.getDeptId());
            userVo.setPrinters(printers);
            List<UserLogistic> logistics = userLogisticService.getList(user.getDeptId());
            userVo.setLogistics(logistics);
            Dept dept = deptService.get(user.getDeptId());
            userVo.setLogisticPriceScheme(priceSchemeService.get(dept.getLogisticPriceSchemeId()));
            userVo.setDryCleaningPriceScheme(priceSchemeService.get(dept.getDryCleaningPriceSchemeId()));
            String supplierTypeDictIds = userVo.getSupplierTypeDictIds();
            if (StringUtils.isNotBlank(supplierTypeDictIds)) {
                List<DictData> supplierTypeList = new ArrayList<>(4);
                for (String code : supplierTypeDictIds.split(",")) {
                    DictData dictData = dictDataService.get(Long.valueOf(code));
                    supplierTypeList.add(dictData);
                }
                userVo.setSupplierTypeList(supplierTypeList);
            }
            if (dept.getParentId() != 100L) {
                userVo.setParentDeptInfo(deptService.get(dept.getParentId()));
            }
            List<UserRole> deptRoleList = userRoleMapper.selectDeptRole(user.getId(), user.getDeptId());
            roleList = deptRoleList;
            List<Role> roles = new ArrayList<>();
            if (deptRoleList != null) {
                for (UserRole userRole : roleList) {
                    Role role = roleMapper.selectByPrimaryKey(userRole.getRoleId());
                    if ("USER".equals(role.getRoleKey()) && !appEnv) {
                        continue;
                    }
                    roles.add(role);
                }
            }
            dept.setRoles(roles);
            userVo.setDeptName(dept.getDeptName());
            userVo.setDeptInfo(dept);
            userVo.setParentDeptId(dept.getParentId());
            ChannelConfig channelConfig = channelConfigMapper.selectByDeptId(user.getDeptId());
            userVo.setChannelId(channelConfig != null ? channelConfig.getChannelId() : "");
        }
        List<Role> roles = new ArrayList<>();
        if (roleList != null) {
            for (UserRole userRole : roleList) {
                Role role = roleMapper.selectByPrimaryKey(userRole.getRoleId());
                if ("USER".equals(role.getRoleKey()) && !appEnv) {
                    continue;
                }
                roles.add(role);
            }
        }
        userVo.setRoles(roles);
        userVo.setDefaultSendManAddress(userAddressService.getDefaultAddress(user.getId(), 1));
        userVo.setDefaultRecManAddress(userAddressService.getDefaultAddress(user.getId(), 2));
       /* if (StringUtils.isNotBlank(userVo.getParentId())) {
            userVo.setParentInfo(this.get(userVo.getParentId()));
        }*/
        /*if (StringUtils.isNotBlank(userVo.getRegimentId())) {
            User regiment = this.get(userVo.getRegimentId());
            if (regiment != null) {
                UserVo regimentVo = new UserVo();
                BeanUtils.copyProperties(regiment, regimentVo);
                regimentVo.setLogistics(userLogisticService.getList(regiment.getOpenid()));
                regimentVo.setLogisticPriceScheme(priceSchemeService.get(regiment.getLogisticPriceSchemeId()));
                regimentVo.setDryCleaningPriceScheme(priceSchemeService.get(regiment.getDryCleaningPriceSchemeId()));
                userVo.setRegimentInfo(regimentVo);
            }
        }*/
        return userVo;
    }

    @Override
    public int userRealName(UserRealName userRealName) {
        User user = null;
        Dept dept = null;
        UserAddress userAddress = null;
        if (StringUtils.isNotBlank(userRealName.getMobile())) {
            userAddress = userAddressService.get(userRealName.getName(), userRealName.getMobile());
        } else {
            user = this.get(userRealName.getUserId());
        }
        if (userRealName.getType() != null && userRealName.getType() == 3){
            dept = deptService.get(userRealName.getDeptId());
        }
        if (user == null && userAddress == null && dept == null) {
            throw new CustomException("实名用户不存在");
        }
        if (userRealName.getType() != 3 && user != null && (StringUtils.isNotBlank(user.getRealId()) || StringUtils.isNotBlank(user.getRealName()))) {
//            throw new CustomException(user.getName() + "该用户已实名");
            return 1;
        }
        if (userRealName.getType() != 3 && userAddress != null && (StringUtils.isNotBlank(userAddress.getRealId()) || StringUtils.isNotBlank(userAddress.getRealName()))) {
//            throw new CustomException(user.getName() + "该用户已实名");
            return 1;
        }
        /*if (userAddress != null && !userRealName.getName().trim().contains(userAddress.getName().trim())){
            throw new CustomException(userAddress.getName() + "实名名称不一致");
        }*/
        String result = WechatHttpUtil.cloudRealNameAuth(userRealName.getIdcard(), userRealName.getName(), "market", secretId, secretKey);
        log.info("real name {}", result);
        if (StringUtils.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            if ("0".equals(jsonObject.getString("code"))) {
                JSONObject data = jsonObject.getJSONObject("result");
                if ("1".equals(data.getString("res"))) {
                    if (userRealName.getType() == 3) {
                        dept.setRealId(data.getString("idcard"));
                        dept.setRealName(data.getString("name"));
                        deptService.update(dept);
                        return 1;
                    }
                    if (user != null) {
                        user.setRealId(data.getString("idcard"));
                        user.setRealName(data.getString("name"));
                        user.setSex(data.getString("sex"));
                        user.setBirthday(data.getString("birthday"));
                        user.setRealAddress(data.getString("address"));
                        user.setIdCardUrl(userRealName.getIdCardUrl());
                        return userMapper.updateByPrimaryKeySelective(user);
                    }
                    if (userAddress != null) {
                        userAddress.setRealId(data.getString("idcard"));
                        userAddress.setRealName(data.getString("name"));
                        userAddress.setIdCardUrl(userRealName.getIdCardUrl());
                        return userAddressService.update(userAddress);
                    }
                } else {
                    log.error("unknow err ");
                    throw new CustomException(data.getString("description"));
                }
            } else {
                throw new CustomException(jsonObject.getString("message"));
            }
        }
        throw new CustomException("实名失败");
    }


    @Override
    public void save(User user) {
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public Object authorUser(String userId, String authorUserId, Long roleId) {
        User user = this.get(userId);
        User author = this.get(authorUserId);
        Role role = roleMapper.selectByPrimaryKey(roleId);
        String parentIds = user.getParentIds();
        author.setParentId(userId);
        if (StringUtils.isNotBlank(parentIds)) {
            List<String> list = JSONArray.parseArray(parentIds, String.class);
            list.add(author.getId());
            author.setParentIds(JSONObject.toJSONString(list));
        } else {
            author.setParentIds(JSONObject.toJSONString(Arrays.asList("0", userId, authorUserId)));
        }
        UserRole userRole = userRoleMapper.select(authorUserId, roleId);
        if (userRole == null) {
            userRole = new UserRole();
            userRole.setUserId(authorUserId);
            userRole.setRoleId(roleId);
            userRoleMapper.insert(userRole);
        }
        author.setLastUpdateTime(new Date());
        return userMapper.updateByPrimaryKey(author);
    }

    @Override
    public Object updateUserDept(String id, Long deptId, String opUserId) {
        User record = this.get(id);
        if (deptId != null){
            UserDept userDept = userDeptMapper.selectByUserIdAndDeptId(id, deptId);
            if (userDept == null){
                userDept = new UserDept();
                userDept.setUserId(id);
                userDept.setDeptId(deptId);
                userDeptMapper.insert(userDept);
            }
        }
        record.setDeptId(deptId);
        record.setUpdateBy(opUserId);
        record.setUpdateTime(new Date());
        return userMapper.updateByPrimaryKey(record);
    }

    @Override
    public Object addUserDept(UserDept userDept, String opUserId) {
        UserDept dept = userDeptMapper.selectByUserIdAndDeptId(userDept.getUserId(), userDept.getDeptId());
        if (Objects.nonNull(dept)){
            throw new CustomException("该用户已经添加过该部门了。");
        }
        return userDeptMapper.insert(userDept);
    }

    @Override
    public void removeDept(UserDept userDept, String openid) {
        UserDept dept = userDeptMapper.selectByUserIdAndDeptId(userDept.getUserId(), userDept.getDeptId());
        if (dept != null){
            userDeptMapper.deleteByPrimaryKey(dept);
        }
    }

    @Override
    public ChannelConfig getChannelConfig(Long deptId) {
        return channelConfigMapper.selectByDeptId(deptId);
    }

    @Override
    public ChannelConfig findChannelConfig(String channelId) {
        return channelConfigMapper.selectByChannelId(channelId);
    }

    @Override
    public void updateChannelConfig(ChannelConfig config, String openid) {
        ChannelConfig channelConfig = getChannelConfig(config.getDeptId());
        if (channelConfig == null){
            channelConfig = new ChannelConfig();
            channelConfig.setCreateTime(new Date());
            channelConfig.setDelFlag("0");
            channelConfig.setStatus("0");
        }
        channelConfig.setDeptId(config.getDeptId());
        channelConfig.setChannelId(config.getChannelId());
        channelConfig.setTalentId(config.getTalentId());
        channelConfig.setTalentSecret(config.getTalentSecret());
        channelConfig.setToken(config.getToken());
        channelConfig.setEncodingAesKey(config.getEncodingAesKey());
        channelConfig.setWindowId(config.getWindowId());
        channelConfig.setWindowSecret(config.getWindowSecret());
        channelConfig.setUserId(config.getUserId());
        channelConfig.setUpdateTime(new Date());
        channelConfig.setUpdateBy(openid);
        if (channelConfig.getId() == null){
            channelConfigMapper.insert(channelConfig);
        } else {
            channelConfigMapper.updateByPrimaryKeySelective(channelConfig);
        }
    }


    @Override
    public List<User> getUserList(String appid, Long deptId) {
        return userMapper.selectByAppidAndDeptId(appid, deptId);
    }

    @Override
    public void clean(String openid) {
        User user = this.get(openid);
        userMapper.deleteByPrimaryKey(user.getId());
        userRoleMapper.deleteByUserId(user.getId());
        userDeptMapper.deleteByUserId(user.getId());
        userLogisticService.delete(user.getId());
        orderService.delete(user.getId());
    }
}
